using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;

namespace IEeee
{
    /// <summary>
    /// Describes what the contents of the attachment is.
    /// </summary>
    enum AttachmentType
    {
        /// <summary>
        /// The source docuement
        /// </summary>
        Document,

        /// <summary>
        /// The contents of an IFrame or Frame element
        /// </summary>
        Frame,

        /// <summary>
        /// A CSS page.
        /// </summary>
        StyleSheet,

        /// <summary>
        /// A script file
        /// </summary>
        Script,

        /// <summary>
        /// An images (not currently used.
        /// </summary>
        Image,
    }

    class AttachmentDetails : IDisposable
    {
        //
        // The location on disk where the file is saved
        //
        private String m_FileName;

        //
        private String m_Name;

        private AttachmentType m_AttachmentType;

        private static int ms_FileNameCounter;

        /// <summary>
        /// Create an AttachmentDetails object.
        /// </summary>
        /// <param name="name">The name of the file - this will be used to create a 
        /// file in the temp directory.</param>
        /// <param name="type">The type of this attachment</param>
        /// <param name="contents">The content of this attachment. This will
        /// be written to [TempDir]/name</param>
        public AttachmentDetails (String tempDirName, String name, AttachmentType type, String fileExtension, String contents)
            : this (tempDirName, name, type, fileExtension, contents, null)
        {

        }

        public static void ResetWorkItemCounter ()
        {
            ms_FileNameCounter = 0;
        }

        /// <summary>
        /// Create an AttachmentDetails object.
        /// </summary>
        /// <param name="name">The name of the file - this will be used to create a 
        /// file in the temp directory.</param>
        /// <param name="type">The type of this attachment</param>
        /// <param name="contents">The content of this attachment. This will
        /// be written to [TempDir]/name</param>
        /// <param name="header">An optional header to be written at the start of the attachment file.
        /// Pass null for this argument if you don't want a header.</param>
        public AttachmentDetails (String tempDirName, String name, AttachmentType type, String fileExtension, String contents, String header)
        {
            ArgTest.IsNotNullOrEmpty (name, "name");
            ArgCorrect.EmptyStringIfNull(ref contents);
            ArgTest.IsNotNullOrEmpty (fileExtension, "fileExtension");
            ArgTest.IsNotNullOrEmpty (tempDirName, "tempDirName");
            Debug.Assert (Directory.Exists (tempDirName), "Temp dir does not exist");

            // Note this is thread safe, but I'm not expecting this
            // to ever run in a multi-threaded environment.
            //
            Interlocked.Increment (ref ms_FileNameCounter);
            String fileName = String.Concat (type.ToString (), " ", ms_FileNameCounter.ToString (), ".", fileExtension);

            m_FileName = Path.Combine (tempDirName, fileName);
            m_Name = name;
            m_AttachmentType = type;

            using (FileStream fs = new FileStream (m_FileName, FileMode.Create, FileAccess.Write))
            {
                StreamWriter sw = new StreamWriter (fs);

                if (String.IsNullOrEmpty (header))
                {
                    sw.WriteLine ("---- Details ----");
                    sw.WriteLine (header);
                    sw.WriteLine ("---- Contents ----");
                }
                sw.Write (contents);
                sw.Flush ();
            }
        }

        /// <summary>
        /// Asserts if this object hasn't be disposed of
        /// </summary>
        ~AttachmentDetails ()
        {
            Debug.Assert (m_FileName == null, "AttachmentDetails object was not Dispossed");
        }

        /// <summary>
        /// Deletes the attachment file of the disk. If this isn't called, the object
        /// will assert when the Finalizer is called.
        /// </summary>
        public void Dispose ()
        {
            try
            {
                File.Delete (m_FileName);
            }
            catch (IOException)
            {
                // naughty, naughty 
            }

            m_FileName = null;
            m_Name = null;

            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// The full path of the saved attachment file.
        /// </summary>
        public String FileName
        {
            get { return m_FileName; }
        }

        /// <summary>
        /// The filename part of the path.
        /// </summary>
        public String Name
        {
            get { return m_Name; }
        }

        /// <summary>
        /// The type of this attachment.
        /// </summary>
        public AttachmentType AttachmentType
        {
            get { return m_AttachmentType; }
        }
    }
}
